<?php

use think\facade\Config;
use think\facade\Cache;
use tmcore\utils\File;

/**
 * 设置初始化缓存信息
 * @param string $type
 * @param string $key
 * @param string $value
 * @return array|bool|mixed
 */
function install_cache($type = 'get', $key = '' , $value = '') {
    $cache = Cache::get('sys_install_info');
    if ($type == 'get') {
        if($key) {
            return $cache[$key]??[];
        } else {
            return $cache;
        }
    } else if ($type == 'set') {
        if($key) {
            $cache[$key] = $value;
            Cache::set('sys_install_info', $cache, 3600 * 6);
        }
        return true;
    } else if ($type == 'delete') {
        Cache::set('sys_install_info', null);
    }
}

/**
 * 获取数据库配置
 * @param array $param 参数
 * @param string $type 类型 get create
 * @param string $name 连接配置标识 默认mysql
 * @return array|mixed
 */
function set_db_config($param, $type = "get", $name= "mysql")
{
    if($type == 'get') {
        $config = Config::get('database');
        return $config['connections'][$name];
    } elseif($type == 'create') {
        $config = Config::get('database');
        $data = [
            'type'     => 'mysql',
            'hostname' => $param['hostname'],
            'database' => isset($param['database'])?$param['database']:null,
            'username' => $param['username'],
            'password' => $param['password'],
            'hostport' => $param['hostport'],
            'prefix'   => isset($param['prefix'])?$param['prefix']:'tm_',
            'params'   => [],
            'charset'  => 'utf8'
        ];
        $config['connections'][$name] = $data;
        Config::set($config, 'database');
        return $data;
    } else {
        return [];
    }
}

/**
 * 环境及函数检测
 * @return array 系统环境数据
 */
function check_env()
{
    // 选项 要求 说明建议 实际状态 检测结果
    $items = [
        'php' => ['PHP版本', '8.0+', PHP_VERSION, 'success'],
        'pdo_mysql' => ['pdo_mysql', '开启', '', 'success'],
        'curl' => ['curl', '开启', '', 'success'],
        'openssl' => ['openssl', '开启', '', 'success'],
        'fileinfo' => ['fileinfo', '开启', '', 'success'],
        'gd' => ['GD库', '2.0', '', 'success'],
        'dom' => ['dom', '开启', '', 'success'],
    ];

    // PHP环境检测
    if ($items['php'][2] < '8.0') {
        $items['php'][3] = 'error';
    }

    // pdo_mysql
    $pdo = extension_loaded('pdo') && extension_loaded('pdo_mysql');
    if(!$pdo) {
        $items['pdo_mysql'][3] = 'error';
    } else {
        $items['pdo_mysql'][2] = '已启用';
    }

    // curl
    $curl = extension_loaded('curl') && function_exists('curl_init');
    if(!$curl) {
        $items['curl'][3] = 'error';
    } else {
        $items['curl'][2] = '已启用';
    }

    // openssl
    $openssl = extension_loaded('openssl');
    if(!$openssl) {
        $items['openssl'][3] = 'error';
    } else {
        $items['openssl'][2] = '已启用';
    }

    // fileinfo
    $fileinfo = extension_loaded('fileinfo');
    if(!$fileinfo) {
        $items['fileinfo'][3] = 'error';
    } else {
        $items['fileinfo'][2] = '已启用';
    }

    //GD库检测
    $tmp = function_exists('gd_info') ? gd_info() : array();
    if (empty($tmp['GD Version'])) {
        $items['gd'][3] = 'error';
    } else {
        $items['gd'][2] = $tmp['GD Version'];
    }

    // dom
    $dom = extension_loaded('dom');
    if(!$dom) {
        $items['dom'][3] = 'error';
    } else {
        $items['dom'][2] = '已启用';
    }

    unset($tmp);

    return $items;
}

/**
 * 目录，文件读写检测
 * @return array 检测数据
 */
function check_dir_file()
{
    $items = [
        ['dir', '可写', 'success', 'app', 'app目录可写'],
        ['dir', '可写', 'success', 'public', 'public目录可写'],
        ['dir', '可写', 'success', 'config', 'config目录可写'],
        ['dir', '可写', 'success', 'data', 'data目录可写'],
        ['dir', '可写', 'success', 'runtime', 'runtime目录可写'],
    ];

    $root_path = app()->getRootPath();

    foreach ($items as &$val) {
        if ('dir' == $val[0]) {
            if (!is_writable($root_path . '/' . $val[3])) {
                $val[2] = 'error';
            }
        } else {
            if (file_exists($val[3])) {
                if (!is_writable($root_path . '/' . $val[3])) {
                    $val[1] = '不可写';
                    $val[2] = 'error';
                }
            } else {
                if (!is_writable($root_path . '/' . $val[3])) {
                    $val[1] = '不存在';
                    $val[2] = 'error';
                }
            }
        }
    }
    return $items;
}

/**
 * 目录，文件读写检测（前端目录）
 * @return array 检测数据
 */
function check_web_dir_file()
{
    $items = [
        ['dir', '可写', 'success', 'admin', 'admin目录可写'],
        ['dir', '可写', 'success', 'uniapp', 'uniapp目录可写'],
        ['dir', '可写', 'success', 'pc', 'pc目录可写'],
    ];

    $sys_path = dirname(app()->getRootPath());

    foreach ($items as &$val) {
        if ('dir' == $val[0]) {
            if (!is_writable($sys_path . '/' . $val[3])) {
                $val[2] = 'error';
            }
        } else {
            if (file_exists($val[3])) {
                if (!is_writable($sys_path . '/' . $val[3])) {
                    $val[1] = '不可写';
                    $val[2] = 'error';
                }
            } else {
                if (!is_writable($sys_path . '/' . $val[3])) {
                    $val[1] = '不存在';
                    $val[2] = 'error';
                }
            }
        }
    }
    return $items;
}

/**
 * 检查系统文件夹
 */
function check_file_dir() {
    // 下载目录
    if (!is_dir(app()->getRootPath() . 'data/download')) {
        File::mk_dir(app()->getRootPath() . 'data/download', 0755, true);
    }
    // 初始化目录
    if (!is_dir(app()->getRootPath() . 'data/install')) {
        File::mk_dir(app()->getRootPath() . 'data/install', 0755, true);
    }
    // excel示例目录
    if (!is_dir(app()->getRootPath() . 'public/uploads/excel')) {
        File::mk_dir(app()->getRootPath() . 'public/uploads/excel', 0755, true);
    }
    // 下载文件目录
    if (!is_dir(app()->getRootPath() . 'public/uploads/files')) {
        File::mk_dir(app()->getRootPath() . 'public/uploads/files', 0755, true);
    }
    // 下载图片目录
    if (!is_dir(app()->getRootPath() . 'public/uploads/images')) {
        File::mk_dir(app()->getRootPath() . 'public/uploads/images', 0755, true);
    }
    // 下载视频目录
    if (!is_dir(app()->getRootPath() . 'public/uploads/videos')) {
        File::mk_dir(app()->getRootPath() . 'public/uploads/videos', 0755, true);
    }
    // 导出目录
    if (!is_dir(app()->getRootPath() . 'data/download/export')) {
        File::mk_dir(app()->getRootPath() . 'data/download/export', 0755, true);
    }
    // 导入目录
    if (!is_dir(app()->getRootPath() . 'data/download/import')) {
        File::mk_dir(app()->getRootPath() . 'data/download/import', 0755, true);
    }
}

/**
 * 写入配置文件
 * @param $config
 * @return bool
 */
function write_config($config){
    if(is_array($config)){
        //读取配置内容
        $conf = file_get_contents(app()->getRootPath() . '.example.env');
        // 替换配置项
        foreach ($config as $name => $value) {
            $conf = str_replace("[{$name}]", $value, $conf);
        }
        // 动态设置数据库配置
        if(isset($config['basename']))$config['database'] = $config['basename'];
        set_db_config($config, 'create');

        check_file_dir();

        $env_path = app()->getRootPath() . '.env';

        //写入应用配置文件
        if(file_put_contents($env_path, $conf)){
            return true;
        } else {
            return false;
        }
    }
}

/**
 * 修改前端工程配置文件
 * @param string $type
 * @return bool
 * @throws Exception
 */
function write_web_config($type = 'admin'){

    try {
        if(!in_array($type,['admin', 'uniapp', 'pc'])){
            throw new \Exception('前端模块参数错误!');
        }

        $sysPath = dirname(app()->getRootPath());

        if($type == 'admin'){
            //读取配置内容
            $conf = file_get_contents($sysPath . '/' . $type . '/.env.example');
            $env_path = $sysPath . '/' . $type . '/.env';

            //写入配置文件
            if(!file_put_contents($env_path, $conf)) throw new \Exception($type . '模块.env配置文件写入失败!');
        }

        //读取开发配置内容
        $dev_conf = file_get_contents($sysPath . '/' . $type . '/.env.development.example');
        $dev_env_path = $sysPath . '/' . $type . '/.env.development';

        //写入开发配置文件
        if(!file_put_contents($dev_env_path, $dev_conf)) throw new \Exception($type . '模块.env.development配置文件写入失败!');

        //读取生产配置内容
        $pro_conf = file_get_contents($sysPath . '/' . $type . '/.env.production.example');
        $pro_env_path = $sysPath . '/' . $type . '/.env.production';

        //写入生产配置文件
        if(!file_put_contents($pro_env_path, $pro_conf)) throw new \Exception($type . '模块.env.production配置文件写入失败!');

        return true;

    } catch (\Exception $e) {
        throw new \Exception($e->getMessage());
    }
}

/**
 * 获取sql数据
 * @param string $sql_path sql文件路径
 * @param string $old_prefix 原表前缀
 * @param string $new_prefix 新表前缀
 * @param string $separator 分隔符 参数可为";\n"或";\r\n"或";\r"
 * @return array|bool
 */
function get_mysql_data($sql_path, $old_prefix = "", $new_prefix = "", $separator = ";\n")
{
    $commenter = array('#', '--');
    //判断文件是否存在
    if (!file_exists($sql_path))
        return false;

    $content = file_get_contents($sql_path);   //读取sql文件
    $content = str_replace(array($old_prefix, "\r"), array($new_prefix, "\n"), $content);//替换前缀

    //通过sql语法的语句分割符进行分割
    $segment = explode($separator, trim($content));
    //去掉注释和多余的空行
    $data = array();
    foreach ($segment as $statement) {
        $sentence = explode("\n", $statement);
        $newStatement = array();
        foreach ($sentence as $subSentence) {
            if ('' != trim($subSentence)) {
                //判断是会否是注释
                $isComment = false;
                foreach ($commenter as $comer) {
                    if (preg_match("/^(" . $comer . ")/is", trim($subSentence))) {
                        $isComment = true;
                        break;
                    }
                }
                //如果不是注释，则认为是sql语句
                if (!$isComment)
                    $newStatement[] = $subSentence;
            }
        }
        $data[] = $newStatement;
    }
    $result = [];
    //组合sql语句
    foreach ($data as $statement) {
        $newStmt = '';
        foreach ($statement as $sentence) {
            $newStmt = $newStmt . trim($sentence) . "\n";
        }
        if (!empty($newStmt)) {
            $match_data = [];
            if (str_contains($newStmt, 'CREATE TABLE')) {
                $match_result = preg_match('/CREATE TABLE [`]?(\\w+)[`]?/is', $newStmt, $match_data);
            } elseif (str_contains($newStmt, 'ALTER TABLE')) {
                $match_result = preg_match('/ALTER TABLE [`]?(\\w+)[`]?/is', $newStmt, $match_data);
            } elseif (str_contains($newStmt, 'INSERT INTO')) {
                $match_result = preg_match('/INSERT INTO [`]?(\\w+)[`]?/is', $newStmt, $match_data);
            } else {
                $match_result = 0;
            }
            if($match_result > 0) {
                $table_name = $match_data[ 1 ];
                if (substr($new_prefix, -1) !== "_") {
                    $new_prefix .= '_';
                }
                $new_table_name = $new_prefix . $table_name;
                $newStmt = implode($table_name, explode($new_table_name, $newStmt, 2));
            }

            $result[] = $newStmt;
        }
    }
    return $result;
}

